core.py 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. # -*- coding: utf-8 -*-
  2. """
  3. certifi.py
  4. ~~~~~~~~~~
  5. This module returns the installation location of cacert.pem or its contents.
  6. """
  7. import os
  8. try:
  9. from importlib.resources import path as get_path, read_text
  10. _CACERT_CTX = None
  11. _CACERT_PATH = None
  12. def where():
  13. # This is slightly terrible, but we want to delay extracting the file
  14. # in cases where we're inside of a zipimport situation until someone
  15. # actually calls where(), but we don't want to re-extract the file
  16. # on every call of where(), so we'll do it once then store it in a
  17. # global variable.
  18. global _CACERT_CTX
  19. global _CACERT_PATH
  20. if _CACERT_PATH is None:
  21. # This is slightly janky, the importlib.resources API wants you to
  22. # manage the cleanup of this file, so it doesn't actually return a
  23. # path, it returns a context manager that will give you the path
  24. # when you enter it and will do any cleanup when you leave it. In
  25. # the common case of not needing a temporary file, it will just
  26. # return the file system location and the __exit__() is a no-op.
  27. #
  28. # We also have to hold onto the actual context manager, because
  29. # it will do the cleanup whenever it gets garbage collected, so
  30. # we will also store that at the global level as well.
  31. _CACERT_CTX = get_path("pip._vendor.certifi", "cacert.pem")
  32. _CACERT_PATH = str(_CACERT_CTX.__enter__())
  33. return _CACERT_PATH
  34. except ImportError:
  35. # This fallback will work for Python versions prior to 3.7 that lack the
  36. # importlib.resources module but relies on the existing `where` function
  37. # so won't address issues with environments like PyOxidizer that don't set
  38. # __file__ on modules.
  39. def read_text(_module, _path, encoding="ascii"):
  40. with open(where(), "r", encoding=encoding) as data:
  41. return data.read()
  42. # If we don't have importlib.resources, then we will just do the old logic
  43. # of assuming we're on the filesystem and munge the path directly.
  44. def where():
  45. f = os.path.dirname(__file__)
  46. return os.path.join(f, "cacert.pem")
  47. def contents():
  48. return read_text("certifi", "cacert.pem", encoding="ascii")